﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text;


namespace Blog.TemplateEngine.Helpers
{
    static class VariableResolver
    {
        public static object Resolve(Context context, string path)
        {
            string[] paths = path.SplitAndTrim('.');

            return VariableResolver.Resolve(context[paths[0]], paths.SubArray(1));
        }

        public static object Resolve(object obj, string[] path)
        {
            if (path.Length == 0)
                return obj;

            Type type = obj.GetType();

            if (typeof(IDictionary).IsAssignableFrom(type))
            {
                IDictionary dictionary = obj as IDictionary;

                return Resolve(dictionary[path[0]], path.SubArray(1));
            }

            PropertyInfo property = type.GetProperty(path[0], BindingFlags.IgnoreCase|BindingFlags.Instance|BindingFlags.Public);

            if (property != null)
            {                
                return Resolve(property.GetValue(obj, null), path.SubArray(1));
            }

            MethodInfo method = type.GetMethod(path[0], BindingFlags.IgnoreCase|BindingFlags.Instance|BindingFlags.Public, null, Type.EmptyTypes, null);
            if (method != null)
            {
                return Resolve(method.Invoke(obj, null), path.SubArray(1));
            }

            if (typeof(Array).IsAssignableFrom(type))
            {
                int index;
                if (!Int32.TryParse(path[0], out index))
                {
                    throw new TemplateException("Invalid index: " + path[0]);
                }
                Array array = obj as Array;

                if (index < 0 || index >= array.Length)
                {
                    throw new TemplateException("Invalid index: " + path[0]);
                }

                return Resolve(array.GetValue(index), path.SubArray(1));
            }

            if (typeof(IList).IsAssignableFrom(type))
            {
                int index;
                if (!Int32.TryParse(path[0], out index))
                {
                    throw new TemplateException("Invalid index: " + path[0]);
                }
                IList list = obj as IList;

                if (index < 0 || index >= list.Count)
                {
                    throw new TemplateException("Invalid index: " + path[0]);
                }

                return Resolve(list[index], path.SubArray(1));
            }

            throw new TemplateException("No method or property named: " + path[0]);
        }
    }
}
